#ifndef __MAPTILESERVER__
#define __MAPTILESERVER__

#include <e32base.h>
#include <lbsposition.h>
#include "PublicTransportTileRequest.h"
#include "ImageDecoderEx.h"
#include "ActiveTarget.h"
#include "WorkerThread.h"
#include "CActiveHelper.h"


struct CTileInfo
	{
	TInt iX, iY, iZoom;
	enum { EPending, EDone, EError, EReady } iStatus;
	CFbsBitmap* iBitmap;
	CFbsBitmap* iLocalBitmap; // references iBitmap but in local thread, will be deleted in local thread
	TInt iBitmapHandle;
	TInt iLocalBitmapHandle;
	CImageDecoder* iImageDecoder;
	CActiveHelper<CTileInfo*>* iImageDecoderActiveHelper;
	TBool iImageDecoderStarted;
	RFile iFile;
	RFile iWriteFile;
	TInt iFileSize;
	HBufC8* iTileData;
	RBuf8 iFileBuf;
	CActiveHelper<CTileInfo*>* iFileReaderActiveHelper;
	CActiveHelper<CTileInfo*>* iFileWriterActiveHelper;
	CPublicTransportTileRequest* iTileRequest;
	CTileInfo() : iBitmap(NULL), iLocalBitmap(NULL), iBitmapHandle(0), iLocalBitmapHandle(0), iImageDecoder(NULL), iImageDecoderActiveHelper(NULL), iTileRequest(NULL), iFileReaderActiveHelper(NULL), iFileWriterActiveHelper(NULL), iTileData(NULL) { iFileBuf.CreateL(0); }
	~CTileInfo() { // this destructor runs on remote thread
		delete iBitmap;
		delete iImageDecoderActiveHelper;
		delete iImageDecoder;
		delete iTileRequest;
		delete iFileReaderActiveHelper;
		delete iFileWriterActiveHelper;
		iFile.Close();
		iFileBuf.Close();
		iWriteFile.Close();
		delete iTileData;
		// we can delete iLocalBitmap here, it will be deleted in local thread
		}
	};

class CMapTileServer : public CBase,
	public MActiveHelperCallback<CTileInfo*>, public MActiveHelperCallback<CImageDecoderEx*>, public MPublicTransportTileCallback, public MActiveHelperCallback<RTimer*>
	{

	public:
	// local thread
	void ConstructL(CWorkerThread* aWorkerThread, TFileName aTileCachePath, TInt aCachedTilesCount);
	~CMapTileServer();
	void SetConnectionInfoL(const RConnection& aConnection, const RSocketServ& aSocketServ);
	void CloseConnectionL();
	void ClearTileCache();
	void SetTileCacheSizeL(TInt aSize);
	void DownloadVisibleTilesL(TCoordinate aCoordinate, TInt aZoomLevel, TSize aSize);
	CFbsBitmap* GetTileBitmap(TInt aTileX, TInt aTileY, TInt aZoomLvel) const;
	void SetCallback(scalp::CFunction<void()>* aCallback);
	
	
	private:
	void RunCallback();
	LManagedPtr< scalp::CFunction<void()> > iCallback;
	RMsgQueue< scalp::CFunction<void()>* > iLocalMsgQueue;
	scalp::CActiveTarget* iLocalMsgQueueActiveTarget;
	void LocalMsgQueueCallbackL();
	void ConnectL();
	TThreadId iLocalThreadId;
	TFileName iTileCachePath;
	CWorkerThread* iWorkerThread;
	TInt iCachedTilesCount;
	// remote thread
	TCoordinate iOrig;
	TInt iZoomLevel;
	TSize iSize;
	TBool iDownloadVisibleTilesPending; // flag to indicate that there is a RemoteDownloadVisibleTilesL call waiting to be executed in the remote thread
	TBool iRunCallbackPending; // flag to indicate that there is a RunCallback call waiting to be executed 
	void RemoteDownloadVisibleTilesL();
	void RemoteSetConnectionInfoL(const RConnection* aConnection, const RSocketServ* aSocketServ, TRequestStatus* aStatus);
	void RemoteCloseConnectionL(TRequestStatus* aStatus);
	void InitWorkerThread();
	void UninitWorkerThread(TRequestStatus* aStatus);
	void InitTileCache();
	RFs iFsTileCache;
	RArray<HBufC*> iTileCache;
	void AddIntoTileCacheL(const TDesC& aFileName);
	TBool FileExistsInTileCacheL(const TDesC& aFileName);
	TInt LoadTileCacheL();
	TInt SaveTileCacheL();
	void RemoteClearTileCache(TRequestStatus* aStatus);
	void RemoteSetTileCacheSizeL(TInt aSize, TRequestStatus* aStatus);
	CPublicTransportTileSession* iPublicTransportTileSession;
	mutable RMutex iTilesMutex;
	mutable RMutex iParamsMutex;
	void DeleteRemoteFunction(scalp::CFunction<void()>* aFunction);
	TSize iTilesSize;
	RTimer iTileTimeoutTimer;
	CActiveHelper<RTimer*>* iTileTimeoutTimerHelper;
	RArray<CTileInfo*> iTiles;
	TInt iStatusCode;
	void TileFileSaved(CActive* aActive, RFile* aFile, const TDesC& aFileName);
	void MPublicTransportTileCallbackRunL(CPublicTransportTileRequest* aTileRequest, TInt aZoom, TInt aTileX, TInt aTileY, TInt aStatus, TInt aLastError, TInt aStatusCode, const TDesC8& aData, void* aUserData);
	TInt MPublicTransportTileCallbackRunError(CPublicTransportTileRequest* aTileRequest, TInt aZoom, TInt aTileX, TInt aTileY, TInt aError, const TDesC8& aData, void* aUserData);
	void MActiveHelperCallbackRunL(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer);
	TInt MActiveHelperCallbackRunError(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer, TInt aError);
	void MActiveHelperCallbackDoCancel(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer);
	void MActiveHelperCallbackRunL(CActiveHelper<CTileInfo*>* aActiveHelper, CTileInfo* aTile);
	TInt MActiveHelperCallbackRunError(CActiveHelper<CTileInfo*>* aActiveHelper, CTileInfo* aTile, TInt aError);
	void MActiveHelperCallbackDoCancel(CActiveHelper<CTileInfo*>* aActiveHelper, CTileInfo* aTile);
	void MActiveHelperCallbackRunL(CActiveHelper<CImageDecoderEx*>* aActiveHelper, CImageDecoderEx* aImageDecoder);
	TInt MActiveHelperCallbackRunError(CActiveHelper<CImageDecoderEx*>* aActiveHelper, CImageDecoderEx* aImageDecoder, TInt aError);
	void MActiveHelperCallbackDoCancel(CActiveHelper<CImageDecoderEx*>* aActiveHelper, CImageDecoderEx* aImageDecoder);
	void TileFileOpened(TInt aError, TFileName aTileFileName, CTileInfo* aTile);
	void CleanupTiles();
	};


#endif// __MAPTILESERVER__
